#include "Instance.hpp"
#include <sstream>

namespace se {

void Instance::Run() // to call in each loop
{
    for(uint32_t i = 0; i < m_objects.size(); i++)
    {
        m_objects[i]->Act(*this);
    }
}

void Instance::Pause() // pause the animations and the timers
{
    for(uint32_t i = 0; i < m_chronos.size(); i++)
    {
        m_chronos[i]->Pause();
    }
    
    //m_drawInst->Pause();
}

void Instance::Resume() // unpause the animations and the timers
{
    for(uint32_t i = 0; i < m_chronos.size(); i++)
    {
        m_chronos[i]->Resume();
    }
    
    //m_drawInst->Resume();
}

std::vector<SimpleObject*> Instance::GetObjects() // to get all objects in the instance
{
    return m_objects;
}

std::vector<SimpleObject*> Instance::GetObjects(Position p, float dist) // to get all objects in the instance and in a range
{
    std::vector<SimpleObject*> objects;
    for(uint32_t i = 0; i < m_objects.size(); i++)
    {
        if(m_objects[i]->Distance(p) < dist) objects.push_back(m_objects[i]);
    }
    return objects;
}

std::vector<SimpleObject*> Instance::GetObjects(SimpleObject* object) // to get all objects touching the object object
{
    std::vector<SimpleObject*> objects;
    for(uint32_t i = 0; i < m_objects.size(); i++)
    {
        if(m_objects[i]->Touch(object)) objects.push_back(m_objects[i]);
    }
    return objects;
}

std::vector<SimpleObject*> Instance::GetObjects(std::string type) // to get all objects of a type in the instance
{
    std::vector<SimpleObject*> objects;
    for(uint32_t i = 0; i < m_objects.size(); i++)
    {
        if(type == m_objects[i]->GetType()) objects.push_back(m_objects[i]);
    }
    return objects;
}

std::vector<SimpleObject*> Instance::GetObjects(std::string type, Position p, float dist) // to get all objects of a type in the instance and in a range
{
    std::vector<SimpleObject*> objects;
    for(uint32_t i = 0; i < m_objects.size(); i++)
    {
        if((type == m_objects[i]->GetType()) && (m_objects[i]->Distance(p) < dist)) objects.push_back(m_objects[i]);
    }
    return objects;
}

std::vector<SimpleObject*> Instance::GetObjects(std::string type, SimpleObject* object) // to get all objects of a type touching the object object
{
    std::vector<SimpleObject*> objects;
    for(uint32_t i = 0; i < m_objects.size(); i++)
    {
        if((type == m_objects[i]->GetType()) && (m_objects[i]->Touch(object))) objects.push_back(m_objects[i]);
    }
    return objects;
}

void Instance::AddObject(SimpleObject* object) // add an object in the instance, cast an error if the object is already in the instance
{
    // searching the object
	int i = m_objects.size()-1;
	while(m_objects[i]!=object && i>=0)
	{
		i--;
	}
	if(i<0) // object not found
	{
        // adding the object
        m_objects.push_back(object);
	} 
	else // object found
	{
		std::stringstream ss;
		ss<<"se::Instance.add_object("<<object<<") failed : the object was already in the instance.";
		throw(std::runtime_error(ss.str()));
	}
	
}

void Instance::RemObject(SimpleObject* object) // remove an object from the instance, cast an error if the object isn't found
{
	// searching the object
	int i = m_objects.size()-1;
	while(m_objects[i]!=object && i>=0)
	{
		i--;
	}
	if(i<0) // object not found
	{
		std::stringstream ss;
		ss<<"se::Instance.rem_object("<<object<<") failed : the object was not found.";
		throw(std::runtime_error(ss.str()));
	}
	else // object found
	{
	    // removing the object
        m_objects[i] = m_objects.back();
        m_objects.pop_back();
	}
}
}//</namespace se>

